const DB = require('../config/sequelize')
const {wechatPayParams} = require('../config/configParams')
const {payment} = require('../config/wechatPay')
const redisConfig = require('../config/redisConfig')
const RabbitMQTool = require('../config/rabbitMQ')

const BackCode = require('../utils/BackCode')
const CodeEnum = require('../utils/CodeEnum')
const RandomTool = require('../utils/RandomTool')
const SecretTool = require('../utils/SecretTool')
const GetUserInfoTool = require('../utils/GetUserInfoTool')

const dayjs = require('dayjs')

const rabbitMQTool = new RabbitMQTool()

const OrderService = {
    query_pay: async (req) => {
        let {id} = req.query
        if (!id) return BackCode.buildError({msg: '缺少必要参数'})
        let token = req.headers.authorization.split(' ').pop()
        let userInfo = SecretTool.jwtVerify(token)
        let orderList = await DB.ProductOrder.findAll({
            where: {product_id: id, account_id: userInfo.id, order_state: 'PAY'},
            raw: true
        })
        if (orderList.length > 0) {
            return BackCode.buildSuccess()
        } else {
            return BackCode.buildResult(CodeEnum.PRODUCT_NO_PAY)
        }
    },
    latest: async (req) => {
        let {id} = req.query
        if (!id) return BackCode.buildError({msg: '缺少必要参数'})
        let latestList = await DB.ProductOrder.findAll({
            where: {product_id: id},
            order: [['gmt_create', 'DESC']],
            limit: 20
        })
        return BackCode.buildSuccessAndData({data: latestList})
    },
    pay: async (req) => {
        let {id, type} = req.body

        let token = req.headers.authorization.split(' ').pop()

        // 获取用户信息
        let userInfo = SecretTool.jwtVerify(token)

        // 获取数据库的用户信息
        let realUserInfo = await DB.Account.findOne({where: {id: userInfo.id}, raw: true})

        // 用户的ip
        let ip = GetUserInfoTool.getIp(req)

        // 生成32位字符串
        let out_trade_no = RandomTool.randomString(32)

        // 根据商品的ID查询商品价格
        let productInfo = await DB.Product.findOne({where: {id}, raw: true})

        // 拼装用户和商品信息插入数据库
        let userPro = {
            account_id: userInfo.id,
            username: userInfo.username,
            user_head_img: userInfo.head_img,
            out_trade_no: out_trade_no,
            total_amount: productInfo.amount,
            pay_amount: productInfo.amount,
            product_id: productInfo.id,
            product_type: productInfo.product_type,
            product_title: productInfo.title,
            product_img: productInfo.cover_img,
            order_state: 'NEW',
            ip: ip
        }

        // 订单推送MQ普通队列
        let userMQ = {account_id: userInfo.id, out_trade_no: out_trade_no}
        rabbitMQTool.sender('order.queue', JSON.stringify(userMQ))

        // 新订单信息插入数据库
        await DB.ProductOrder.create(userPro)

        // 微信支付二维码
        if (type === 'PC') {
            let result = await payment.native({
                description: '小滴课堂-测试',
                out_trade_no,  // 正式
                amount: {
                    // total: Number(productInfo.amount) * 100,  // 正式
                    total: 1 // 测试
                }
            })
            return BackCode.buildSuccessAndData({data: {code_url: JSON.parse(result.data).code_url, out_trade_no}})
        }

        // 生成签名
        function getSign({appid, timestamp, noncestr, prepay_id, type} = {}) {
            const parsms = [appid, timestamp, noncestr]
            // APP支付和小程序不同
            type === 'WEAPP' ? parsms.push(`prepay_id=${prepay_id}`) : parsms.push(prepay_id)
            const signatureStr = parsms.join('\n') + '\n'
            return payment.rsaSign(signatureStr, wechatPayParams.private_key)
        }

        // app微信支付
        if (type === 'APP') {
            console.log(id)
            let result = await payment.app({
                description: '小滴课堂-测试',
                out_trade_no, // 正式
                amount: {
                    // total: Number(productInfo.amount) * 100,  // 正式
                    total: 1 // 测试
                }
            })
            const prepay_id = JSON.parse(result.data).prepay_id
            const timestamp = Date.parse(new Date())
            const noncestr = RandomTool.randomString(32)

            const sign = getSign({noncestr, timestamp, prepay_id})
            console.log(sign)
            return BackCode.buildSuccessAndData({
                data: {
                    noncestr,
                    timestamp,
                    sign: getSign({noncestr, timestamp, prepay_id}),
                    appid: wechatPayParams.app_appid,
                    partnerid: wechatPayParams.mchid,
                    prepayid: prepay_id,
                    package: 'Sign=WXPay'
                }
            })
        }

        if (type === 'WEAPP') {
            // 微信小程序具体逻辑
            let result = await payment.jsapi({
                description: '小滴课堂-测试',
                out_trade_no, // 正式
                amount: {
                    // total: Number(productInfo.amount) * 100,  // 正式
                    total: 1 // 测试
                },
                payer: {
                    openid: realUserInfo.openid
                }
            })
            const prepay_id = JSON.parse(result.data).prepay_id
            const timestamp = Date.parse(new Date())
            const noncestr = RandomTool.randomString(32)

            return BackCode.buildSuccessAndData({
                data: {
                    appid: wechatPayParams.weapp_appid,
                    timeStamp: String(timestamp),
                    nonceStr: noncestr,
                    package: 'prepay_id=' + prepay_id,
                    signType: 'RSA',
                    paySign: getSign({appid: wechatPayParams.weapp_appid, noncestr, timestamp, prepay_id, type: 'WEAPP'}),
                    partnerid: wechatPayParams.mchid
                }
            })
        }
    },

    callback: async (req) => {
        let timestamp = req.header('Wechatpay-Timestamp')
        let nonce = req.header('Wechatpay-Nonce')
        let serial = req.header('Wechatpay-Serial')
        let signature = req.header('Wechatpay-Signature')
        let body = req.body

        // 1.校验收到的请求是否来自微信服务器和平台证书是否一致
        let result = await payment.verifySign({
            timestamp,
            nonce,
            serial,
            signature,
            body
        })
        if (!result) {
            return
        }

        // 2.解密body中的数据，拿到用户订单信息
        let bufferoOne = payment.decode(body.resource)
        let json = JSON.parse(bufferoOne.toString('utf8'))
        let {out_trade_no, trade_state} = json
        console.log(json)
        if (trade_state === 'SUCCESS') {
            // 3.根据微信服务器返回的订单信息更新数据库中改订单的支付状态
            await DB.ProductOrder.update({order_state: 'PAY'}, {where: {out_trade_no}})
            // 4.更新redis课程热门排行榜数据
            let productItem = await DB.ProductOrder.findOne({where: {out_trade_no}, raw: true})
            if (!productItem) {
                return
            }
            let memberInfo = {
                id: productItem.product_id,
                title: productItem.product_title,
                img: productItem.product_img,
            }
            let time = dayjs(Date.now()).format('YYYY-MM-DD')
            await redisConfig.zincrby({
                key: `${time}:rank:hot_product`,
                increment: 1,
                member: JSON.stringify(memberInfo)
            })
        }
        return BackCode.buildSuccess()
    },
    query_state: async (req) => {
        let {out_trade_no} = req.query
        if (!out_trade_no) return BackCode.buildError({msg: '缺少必要参数'})
        let token = req.headers.authorization.split(' ').pop()
        let userInfo = SecretTool.jwtVerify(token)
        let order_state = (await DB.ProductOrder.findOne({
            where: {out_trade_no, account_id: userInfo.id},
            raw: true
        })).order_state
        return BackCode.buildSuccessAndData({data: {order_state}})
    },
    list: async (req) => {
        let {state, page, size} = req.body
        let token = req.headers.authorization.split(' ').pop()
        let userInfo = SecretTool.jwtVerify(token)

        let current_data = [], total_record = null
        if (state) {
            // 不同状态的订单列表
            let {count, rows} = await DB.ProductOrder.findAndCountAll({
                where: {account_id: userInfo.id, order_state: state},
                order: [['gmt_create', 'DESC']],
                offset: Number((page - 1) * size),
                limit: Number(size),
                del: 0
            })
            current_data = rows
            total_record = count
        } else {
            // 全部订单
            let {count, rows} = await DB.ProductOrder.findAndCountAll({
                where: {account_id: userInfo.id},
                order: [['gmt_create', 'DESC']],
                offset: Number((page - 1) * size),
                limit: Number(size),
                del: 0
            })
            current_data = rows
            total_record = count
        }
        // 计算总页数
        let total_page = null
        total_record % size === 0 ? (total_page = total_record / size) : (total_page = Math.ceil(total_record / size))
        return BackCode.buildSuccessAndData({data: {current_data, total_page: total_page, total_record: total_record}})
    }
}
module.exports = OrderService